{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "beObUOFyuRjT"
      },
      "source": [
        "##### Copyright 2018 The TF-Agents Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "nQnmcm0oI1Q-"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "s6D70EeAZe-Q"
      },
      "source": [
        "# ドライバ\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/agents/tutorials/4_drivers_tutorial\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\"> TensorFlow.orgで表示</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/agents/tutorials/4_drivers_tutorial.ipynb\">     <img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colabで実行</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/agents/tutorials/4_drivers_tutorial.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub でソースを表示{</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/agents/tutorials/4_drivers_tutorial.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">ノートブックをダウンロード/a0}</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8aPHF9kXFggA"
      },
      "source": [
        "## はじめに\n",
        "\n",
        "強化学習の一般的なパターンは、指定された数のステップまたはエピソードで環境でポリシーを実行することです。 これは、データ収集、評価、およびエージェントの動画の生成などの際に行われます。\n",
        "\n",
        "Pythonでは比較的簡単に記述できますが、 `tf.while`ループ、`tf.cond` や`tf.control_dependencies`が含まれるため、TensorFlowでの記述やデバッグは非常に複雑になります。そのため、この実行ループの概念を`driver`と呼ばれるクラスに抽象化する実装が提供されています。これはPythonとTensorFlowの両方で十分にテストされています。\n",
        "\n",
        "さらに、各ステップでドライバに提供されるデータは、Trajectoryという名前のタプルに保存され、再生バッファーやメトリックなどのオブザーバーにブロードキャストされます。 このデータには、環境からの観察、ポリシーが推奨する行動、取得した報酬、その時点と次のステップのタイプなどが含まれます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "t7PM1QfMZqkS"
      },
      "source": [
        "## セットアップ"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0w-Ykwl1bn4v"
      },
      "source": [
        "TF-agentまたはgymをまだインストールしていない場合は、以下を実行します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TnE2CgilrngG"
      },
      "outputs": [],
      "source": [
        "!pip install tf-agents\n",
        "!pip install gym"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "whYNP894FSkA"
      },
      "outputs": [],
      "source": [
        "from __future__ import absolute_import\n",
        "from __future__ import division\n",
        "from __future__ import print_function\n",
        "\n",
        "import tensorflow as tf\n",
        "\n",
        "\n",
        "from tf_agents.environments import suite_gym\n",
        "from tf_agents.environments import tf_py_environment\n",
        "from tf_agents.policies import random_py_policy\n",
        "from tf_agents.policies import random_tf_policy\n",
        "from tf_agents.metrics import py_metrics\n",
        "from tf_agents.metrics import tf_metrics\n",
        "from tf_agents.drivers import py_driver\n",
        "from tf_agents.drivers import dynamic_episode_driver\n",
        "\n",
        "tf.compat.v1.enable_v2_behavior()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9V7DEcB8IeiQ"
      },
      "source": [
        "## Pythonドライバ\n",
        "\n",
        "`PyDriver`クラスは、Python環境、Pythonポリシー、および各ステップで更新するオブザーバーのリストを受け取ります。主なメソッドは`run()`で、終了基準（ステップ数が`max_steps` に達するか、エピソード数が`max_episodes`に達する）が少なくとも1つ満たされるまで、ポリシーに基づいた行動を環境で実行します。\n",
        "\n",
        "大まかな実装は次のとおりです。\n",
        "\n",
        "```python\n",
        "class PyDriver(object):\n",
        "\n",
        "  def __init__(self, env, policy, observers, max_steps=1, max_episodes=1):\n",
        "    self._env = env\n",
        "    self._policy = policy\n",
        "    self._observers = observers or []\n",
        "    self._max_steps = max_steps or np.inf\n",
        "    self._max_episodes = max_episodes or np.inf\n",
        "\n",
        "  def run(self, time_step, policy_state=()):\n",
        "    num_steps = 0\n",
        "    num_episodes = 0\n",
        "    while num_steps < self._max_steps and num_episodes < self._max_episodes:\n",
        "\n",
        "      # Compute an action using the policy for the given time_step\n",
        "      action_step = self._policy.action(time_step, policy_state)\n",
        "\n",
        "      # Apply the action to the environment and get the next step\n",
        "      next_time_step = self._env.step(action_step.action)\n",
        "\n",
        "      # Package information into a trajectory\n",
        "      traj = trajectory.Trajectory(\n",
        "         time_step.step_type,\n",
        "         time_step.observation,\n",
        "         action_step.action,\n",
        "         action_step.info,\n",
        "         next_time_step.step_type,\n",
        "         next_time_step.reward,\n",
        "         next_time_step.discount)\n",
        "\n",
        "      for observer in self._observers:\n",
        "        observer(traj)\n",
        "\n",
        "      # Update statistics to check termination\n",
        "      num_episodes += np.sum(traj.is_last())\n",
        "      num_steps += np.sum(~traj.is_boundary())\n",
        "\n",
        "      time_step = next_time_step\n",
        "      policy_state = action_step.state\n",
        "\n",
        "    return time_step, policy_state\n",
        "\n",
        "```\n",
        "\n",
        "次に、CartPole環境でランダムポリシーを実行し、結果を再生バッファーに保存し、いくつかのメトリックを計算する例を見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Dj4_-77_5ExP"
      },
      "outputs": [],
      "source": [
        "env = suite_gym.load('CartPole-v0')\n",
        "policy = random_py_policy.RandomPyPolicy(time_step_spec=env.time_step_spec(), \n",
        "                                         action_spec=env.action_spec())\n",
        "replay_buffer = []\n",
        "metric = py_metrics.AverageReturnMetric()\n",
        "observers = [replay_buffer.append, metric]\n",
        "driver = py_driver.PyDriver(\n",
        "    env, policy, observers, max_steps=20, max_episodes=1)\n",
        "\n",
        "initial_time_step = env.reset()\n",
        "final_time_step, _ = driver.run(initial_time_step)\n",
        "\n",
        "print('Replay Buffer:')\n",
        "for traj in replay_buffer:\n",
        "  print(traj)\n",
        "\n",
        "print('Average Return: ', metric.result())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "X3Yrxg36Ik1x"
      },
      "source": [
        "## TensorFlowドライバ\n",
        "\n",
        "また、TensorFlowには、Pythonドライバと機能的に似ているドライバがありますが、TensorFlowドライバでは、TF環境、TFポリシー、TFオブザーバーなどを使用します。現在、次の2つのTensorFlowドライバがあります。`DynamicStepDriver`は、指定された数の（有効な）環境ステップの後に終了します。`DynamicEpisodeDriver`、指定された数のエピソードの後に終了します。 では、実際のDynamicEpisodeの例を見てみましょう。\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "WC4ba3ObSceA"
      },
      "outputs": [],
      "source": [
        "env = suite_gym.load('CartPole-v0')\n",
        "tf_env = tf_py_environment.TFPyEnvironment(env)\n",
        "\n",
        "tf_policy = random_tf_policy.RandomTFPolicy(action_spec=tf_env.action_spec(),\n",
        "                                            time_step_spec=tf_env.time_step_spec())\n",
        "\n",
        "\n",
        "num_episodes = tf_metrics.NumberOfEpisodes()\n",
        "env_steps = tf_metrics.EnvironmentSteps()\n",
        "observers = [num_episodes, env_steps]\n",
        "driver = dynamic_episode_driver.DynamicEpisodeDriver(\n",
        "    tf_env, tf_policy, observers, num_episodes=2)\n",
        "\n",
        "# Initial driver.run will reset the environment and initialize the policy.\n",
        "final_time_step, policy_state = driver.run()\n",
        "\n",
        "print('final_time_step', final_time_step)\n",
        "print('Number of Steps: ', env_steps.result().numpy())\n",
        "print('Number of Episodes: ', num_episodes.result().numpy())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Sz5jhHnU0fX1"
      },
      "outputs": [],
      "source": [
        "# Continue running from previous state\n",
        "final_time_step, _ = driver.run(final_time_step, policy_state)\n",
        "\n",
        "print('final_time_step', final_time_step)\n",
        "print('Number of Steps: ', env_steps.result().numpy())\n",
        "print('Number of Episodes: ', num_episodes.result().numpy())"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "4_drivers_tutorial.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
